<template>
  <view class="chat-panel">
    <!-- 头部 -->
    <view class="chat-header">
      <text class="header-title">知汛智能助手</text>
      <view class="header-status">
        <view class="status-dot" :class="{ connected: isConnected }"></view>
        <text class="status-text">{{ isConnected ? '已连接' : '未连接' }}</text>
      </view>
    </view>
    
    <!-- 页面模态框 -->
    <PageModal 
      :visible="modalVisible"
      :url="modalUrl"
      :title="modalTitle"
      @close="closeModal"
    />
    
    <!-- 预报历史模态框 -->
    <view 
      v-if="historyModalVisible" 
      class="history-modal-overlay"
      @click="closeForecastHistory"
    >
      <view class="history-modal-content" @click.stop>
        <view class="history-modal-header">
          <text class="history-modal-title">📚 预报历史记录</text>
          <button class="history-modal-close" @click="closeForecastHistory">✕</button>
        </view>
        <view class="history-modal-body">
          <ForecastHistory 
            :stcd="stcd"
            :start-time="historyStartTime"
          />
        </view>
      </view>
    </view>

    <!-- 假拟降雨模态框 -->
    <view 
      v-if="hypotheticalModalVisible" 
      class="history-modal-overlay"
      @click="closeHypotheticalRainfall"
    >
      <view class="history-modal-content" @click.stop>
        <HypotheticalRainfall 
          :session-id="$props.lastSessionId || ''"
          :llm-config="llmHypotheticalConfig"
          @close="closeHypotheticalRainfall"
        />
      </view>
    </view>

    <!-- 消息列表 -->
    <view class="chat-messages" ref="messagesContainer">
      <view 
        v-for="(message, index) in messages" 
        :key="index"
        class="message-item"
        :class="message.role"
      >
        <view class="message-avatar">
          <text class="avatar-icon">{{ message.role === 'user' ? '👤' : '🤖' }}</text>
        </view>
        <view class="message-content">
          <view class="message-header">
            <text class="message-sender">{{ message.role === 'user' ? '我' : '知汛助手' }}</text>
            <text class="message-time">{{ formatTime(message.timestamp) }}</text>
          </view>
          <view class="message-text">
            <!-- 如果是markdown格式，使用MarkdownRenderer组件 -->
            <MarkdownRenderer 
              v-if="message.isMarkdown" 
              :content="message.content"
            />
            <!-- 普通文本 -->
            <text v-else>{{ message.content }}</text>
          </view>
          <!-- 命令建议 -->
          <view class="message-actions" v-if="message.actions && message.actions.length > 0">
            <button 
              v-for="action in message.actions" 
              :key="action.label"
              class="action-btn"
              :class="action.type || 'default'"
              @click="executeAction(action)"
            >
              {{ action.label }}
            </button>
          </view>
        </view>
      </view>

      <!-- 输入中提示 -->
      <view class="message-item assistant typing" v-if="isTyping">
        <view class="message-avatar">
          <text class="avatar-icon">🤖</text>
        </view>
        <view class="message-content">
          <view class="typing-indicator">
            <span class="dot"></span>
            <span class="dot"></span>
            <span class="dot"></span>
          </view>
        </view>
      </view>
    </view>

    <!-- 预报方案选择（首次显示） -->
    <view class="scheme-selection" v-if="!selectedScheme && isConnected">
      <!-- 背景装饰 -->
      <view class="bg-decoration">
        <view class="decoration-circle circle-1"></view>
        <view class="decoration-circle circle-2"></view>
        <view class="decoration-circle circle-3"></view>
      </view>
      
      <!-- 头部区域 -->
      <view class="selection-header">
        <view class="header-icon-wrapper">
          <text class="header-icon">🎯</text>
        </view>
        <text class="selection-title">选择洪水预报方案</text>
        <text class="selection-desc">
          <text class="station-badge">测站 {{ stcd }}</text> 支持的预报模型
        </text>
      </view>
      
      <!-- 方案卡片 -->
      <view class="scheme-cards">
        <view 
          v-for="(scheme, index) in availableSchemes" 
          :key="scheme.value"
          class="scheme-option-card"
          :class="'card-delay-' + index"
          @click="selectScheme(scheme)"
        >
          <view class="card-glow"></view>
          <view class="scheme-card-left">
            <view class="scheme-icon-bg">
              <text class="scheme-card-icon">{{ scheme.icon }}</text>
            </view>
            <view class="scheme-card-content">
              <text class="scheme-card-name">{{ scheme.label }}</text>
              <text class="scheme-card-desc">{{ getSchemeDesc(scheme.model_type) }}</text>
            </view>
          </view>
          <view class="scheme-card-action">
            <view class="action-circle">
              <svg width="20" height="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                <path d="M9 5l7 7-7 7" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
              </svg>
            </view>
          </view>
        </view>
      </view>
      
      <!-- 底部提示 -->
      <view class="selection-note">
        <view class="note-icon-wrapper">
          <svg width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
            <path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z" fill="currentColor"/>
          </svg>
        </view>
        <text class="note-text">选择方案后，系统将自动加载模型参数和配置</text>
      </view>
    </view>

    <!-- 快捷指令（已选择方案后显示） -->
    <view class="quick-commands" v-if="!hasMessages && selectedScheme">
      <text class="commands-title">快捷指令</text>
      <view class="commands-grid">
        <view 
          v-for="cmd in quickCommands" 
          :key="cmd.label"
          class="command-card"
          @click="sendQuickCommand(cmd.command)"
        >
          <text class="command-icon">{{ cmd.icon }}</text>
          <text class="command-label">{{ cmd.label }}</text>
        </view>
      </view>
    </view>

    <!-- 输入框 -->
    <view class="chat-input-container">
      <!-- 命令面板（在输入框上方） -->
      <view class="command-palette" v-if="showCommandPalette">
        <view class="command-palette-header">
          <text class="palette-title">💬 快速指令</text>
          <text class="palette-hint">{{ hasSearchText ? '↑↓ 选择  Enter 执行' : '输入关键词搜索' }}  Esc 取消</text>
        </view>
        
        <!-- 有搜索词：显示扁平列表 -->
        <view class="command-palette-list" v-if="hasSearchText">
          <view 
            v-for="(cmd, index) in filteredCommands" 
            :key="cmd.command"
            class="palette-command-item"
            :class="{ active: selectedCommandIndex === index }"
            @click.stop="executeCommand(cmd)"
            @mousedown.stop.prevent
          >
            <view class="cmd-icon-wrapper" :style="{ backgroundColor: cmd.groupColor + '20' }">
              <text class="palette-cmd-icon">{{ cmd.icon }}</text>
            </view>
            <view class="cmd-content">
              <text class="palette-cmd-label">{{ cmd.label }}</text>
              <text class="palette-cmd-group">{{ cmd.groupTitle }}</text>
            </view>
          </view>
          <view class="palette-empty" v-if="filteredCommands.length === 0">
            <text class="empty-icon">🔍</text>
            <text class="empty-text">未找到匹配的指令</text>
          </view>
        </view>
        
        <!-- 无搜索词：显示分组卡片 -->
        <view class="command-groups" v-else>
          <view 
            v-for="group in commandGroups" 
            :key="group.title"
            class="command-group"
          >
            <view class="group-header" :style="{ borderColor: group.color }">
              <text class="group-icon">{{ group.icon }}</text>
              <text class="group-title">{{ group.title }}</text>
            </view>
            <view class="group-commands">
              <view 
                v-for="cmd in group.commands" 
                :key="cmd.command"
                class="group-command-item"
                @click.stop="executeCommand(cmd)"
                @mousedown.stop.prevent
              >
                <view class="cmd-icon-wrapper" :style="{ backgroundColor: group.color + '20' }">
                  <text class="cmd-icon">{{ cmd.icon }}</text>
                </view>
                <view class="cmd-info">
                  <text class="cmd-name">{{ cmd.label }}</text>
                  <text class="cmd-desc">{{ cmd.desc }}</text>
                </view>
              </view>
            </view>
          </view>
        </view>
      </view>
      
      <view class="input-wrapper">
        <textarea 
          ref="inputRef"
          class="chat-input"
          v-model="inputText"
          placeholder="输入消息，Enter 发送..."
          :auto-height="true"
          :maxlength="500"
          :cursor-spacing="100"
          :show-confirm-bar="false"
          @input="handleInput"
          @confirm="sendMessage"
          @focus="handleFocus"
          @keydown="handleKeyDown"
        />
        <button 
          class="send-btn"
          :disabled="!canSend"
          @click="sendMessage"
        >
          <text class="send-icon">{{ canSend ? '➤' : '○' }}</text>
        </button>
      </view>
      <view class="input-hint" v-if="inputFocused && !showCommandPalette">
        <text>💡 提示：Enter 发送 | Shift+Enter 换行 | 输入 "/" 唤起指令</text>
      </view>
    </view>
  </view>
</template>

<script>
import { ref, computed, onMounted, onUnmounted, nextTick, watch } from 'vue'
import { forecastApi, llmApi } from '../api/api.js'
import MarkdownRenderer from '../../ChatComponents/MarkdownRenderer.vue'
import PageModal from '../utils/PageModal.vue'
import ForecastHistory from '../history/ForecastHistory.vue'
import HypotheticalRainfall from './HypotheticalRainfall.vue'
import { v4 as uuidv4 } from 'uuid'

export default {
  name: 'ChatPanel',
  components: {
    MarkdownRenderer,
    PageModal,
    ForecastHistory,
    HypotheticalRainfall
  },
  props: {
    stcd: {
      type: String,
      required: true
    },
    selectedScheme: {
      type: String,
      default: null
    },
    sessionId: {
      type: String,
      default: null
    },
    lastSessionId: {
      type: String,
      default: null
    },
    currentParams: {
      type: Object,
      default: () => ({})
    },
    forecastStartTime: {
      type: String,
      default: null
    }
  },
  emits: ['command', 'scheme-change', 'params-updated'],
  setup(props, { emit }) {
    // 🔍 调试：组件初始化时打印所有 props
    console.log('🎯 [ChatPanel.vue] setup 初始化，所有 props:', {
      stcd: props.stcd,
      selectedScheme: props.selectedScheme,
      sessionId: props.sessionId,
      lastSessionId: props.lastSessionId,
      hasLastSessionId: !!props.lastSessionId,
      forecastStartTime: props.forecastStartTime
    })
    
    const messages = ref([])
    const inputText = ref('')
    const inputFocused = ref(false)
    const isConnected = ref(false)
    const isTyping = ref(false)
    const messagesContainer = ref(null)
    const inputRef = ref(null)
    const ws = ref(null)
    const availableSchemes = ref([])
    
    // LLM对话相关
    const conversationId = ref(uuidv4())
    const isLLMThinking = ref(false)
    
    // 页面模态框相关
    const modalVisible = ref(false)
    const modalUrl = ref('')
    const modalTitle = ref('')
    
    // 预报历史模态框相关
    const historyModalVisible = ref(false)
    const historyStartTime = ref('')
    
    // 假拟降雨模态框相关
    const hypotheticalModalVisible = ref(false)
    const llmHypotheticalConfig = ref(null)
    
    // 监控 lastSessionId 变化（调试用）
    watch(() => props.lastSessionId, (newVal, oldVal) => {
      console.log('🔍 ChatPanel lastSessionId 变化:', {
        oldVal,
        newVal,
        hasValue: !!newVal
      })
    }, { immediate: true })
    
    // 命令面板相关
    const showCommandPalette = ref(false)
    const selectedCommandIndex = ref(0)
    
    // 分组命令列表
    const commandGroups = [
      {
        title: '预报操作',
        icon: '📊',
        color: '#667eea',
        commands: [
          { icon: '🔄', label: '切换预报方案', command: 'switch_scheme', desc: '选择其他预报模型' },
          { icon: '📝', label: '修改模型参数', command: 'view_params', desc: '调整水文模型参数' },
          { icon: '⚙️', label: '配置预报时段', command: 'config_time', desc: '设置预报时间范围' },
          { icon: '🌧️', label: '编辑降雨数据', command: 'edit_rainfall', desc: '输入降雨观测数据' },
          { icon: '📈', label: '查看预报结果', command: 'view_result', desc: '查看预报成果' },
          { icon: '🌦️', label: '假拟降雨场景', command: 'hypothetical_rainfall', desc: '生成不同降雨量的预报对比' }
        ]
      },
      {
        title: '外部系统',
        icon: '🔗',
        color: '#f093fb',
        commands: [
          { icon: '🌦️', label: '东三省天气预报', command: 'weather_forecast', desc: '查看气象预报信息' },
          { icon: '💧', label: '水库雨情', command: 'rainfall_detail', desc: '查看测站雨情数据' },
          { icon: '🌊', label: '水库水情', command: 'water_detail', desc: '查看测站水情数据' },
          { icon: '📚', label: '预报历史记录', command: 'forecast_history', desc: '查看历史预报数据' }
        ]
      }
    ]
    
    // 扁平化的命令列表（用于搜索）
    const commandList = commandGroups.flatMap(group => 
      group.commands.map(cmd => ({
        ...cmd,
        groupTitle: group.title,
        groupColor: group.color
      }))
    )

    const quickCommands = [
      { icon: '⚙️', label: '模型参数', command: '显示当前的水文模型参数配置' },
      { icon: '🌧️', label: '降雨数据', command: '生成一组测试降雨数据' },
      { icon: '🚀', label: '执行预报', command: '执行洪水预报计算' },
      { icon: '📊', label: '预报结果', command: '显示洪水预报结果' },
      { icon: '🔄', label: '切换方案', command: '我要切换预报方案' },
      { icon: '❓', label: '使用帮助', command: '我需要帮助，请告诉我可以做什么' }
    ]
    
    // 是否有搜索文本
    const hasSearchText = computed(() => {
      const searchText = inputText.value.slice(1).trim()
      return searchText.length > 0
    })
    
    // 过滤后的命令列表（支持模糊搜索）
    const filteredCommands = computed(() => {
      if (!showCommandPalette.value) return []
      
      const searchText = inputText.value.slice(1).trim().toLowerCase() // 去掉"/"
      if (!searchText) {
        return []
      }
      
      return commandList.filter(cmd => 
        cmd.label.toLowerCase().includes(searchText) ||
        cmd.desc.toLowerCase().includes(searchText)
      )
    })

    const hasMessages = computed(() => messages.value.length > 0)
    const canSend = computed(() => inputText.value.trim().length > 0 && isConnected.value)

    // 加载预报方案
    const loadSchemes = async () => {
      try {
        const schemes = await forecastApi.getAvailableSchemes(props.stcd)
        availableSchemes.value = schemes
      } catch (error) {
        console.error('加载预报方案失败:', error)
      }
    }

    // 选择方案
    const selectScheme = (schemeData) => {
      // 可以接收scheme对象或scheme.value
      let scheme
      if (typeof schemeData === 'object') {
        scheme = schemeData
      } else {
        scheme = availableSchemes.value.find(s => s.value === schemeData)
        if (!scheme) return
      }
      
      // 发送完整的方案对象（包含id）
      emit('scheme-change', scheme)
      
      // 添加消息
      messages.value.push({
        role: 'user',
        content: `选择预报方案: ${scheme.label}`,
        timestamp: new Date().toISOString()
      })
      
      // AI响应
      setTimeout(() => {
        addAIMessage(
          `已选择预报方案：**${scheme.label}**\n\n正在初始化水文模型运行环境...\n\n您可以进行以下操作：`,
          [
            { label: '🌧️ 降雨数据', command: 'edit_rainfall' },
            { label: '📝 模型参数', command: 'view_params' },
            { label: '⚙️ 时段配置', command: 'config_time' }
          ]
        )
      }, 500)
      
      scrollToBottom()
    }

    // 连接WebSocket
    const connectWebSocket = () => {
      try {
        // Mock WebSocket连接
        // 实际使用时替换为真实的WebSocket地址
        // ws.value = new WebSocket('ws://localhost:8000/ws/chat')
        
        // 模拟连接成功
        setTimeout(() => {
          isConnected.value = true
          if (!props.selectedScheme) {
            // 如果未选择方案，显示欢迎消息
            addSystemMessage('👋 欢迎使用知汛洪水预报系统！\n\n请先选择适合测站的预报方案以开始工作。')
          } else {
            // 已选择方案
            addSystemMessage(`当前预报方案：${props.selectedScheme}\n\n知汛助手已就绪，可以为您提供预报辅助操作。`)
          }
        }, 500)

        // 实际WebSocket事件处理
        /*
        ws.value.onopen = () => {
          isConnected.value = true
          addSystemMessage('已连接到AI助手')
        }

        ws.value.onmessage = (event) => {
          const data = JSON.parse(event.data)
          handleAIResponse(data)
        }

        ws.value.onerror = (error) => {
          console.error('WebSocket错误:', error)
          isConnected.value = false
        }

        ws.value.onclose = () => {
          isConnected.value = false
          addSystemMessage('连接已断开')
        }
        */
      } catch (error) {
        console.error('连接失败:', error)
      }
    }

    // 添加AI消息（带操作建议）
    const addAIMessage = (content, actions = []) => {
      messages.value.push({
        role: 'assistant',
        content,
        actions,
        timestamp: new Date().toISOString()
      })
      scrollToBottom()
    }
    
    // 添加系统消息（供父组件调用）
    const addSystemMessage = (content, actions = [], isMarkdown = false) => {
      console.log('📨 添加系统消息:', { content: content.substring(0, 100), isMarkdown, actions })
      messages.value.push({
        role: 'assistant',
        content,
        actions,
        isMarkdown,
        timestamp: new Date().toISOString()
      })
      console.log('📋 当前消息列表长度:', messages.value.length)
      scrollToBottom()
      return true
    }
    
    /* 移除：Markdown解析已迁移到 MarkdownRenderer 组件
    const parseMarkdown = (markdown) => {
      ...
    }
    */

    // 处理输入（检测"/"）
    const handleInput = (e) => {
      const text = inputText.value
      
      console.log('输入变化:', text, '长度:', text.length)
      
      // 检测是否输入"/"
      if (text.startsWith('/')) {
        showCommandPalette.value = true
        selectedCommandIndex.value = 0
        console.log('显示命令面板')
        
        // 确保输入框保持焦点
        nextTick(() => {
          const textarea = document.querySelector('.chat-input')
          if (textarea) {
            textarea.focus()
          }
        })
      } else {
        showCommandPalette.value = false
        console.log('隐藏命令面板')
      }
    }
    
    // 处理键盘事件
    const handleKeyDown = (e) => {
      // ESC 键：关闭命令面板
      if (e.key === 'Escape' || e.keyCode === 27) {
        if (showCommandPalette.value) {
          e.preventDefault()
          showCommandPalette.value = false
          inputText.value = ''
          return
        }
      }
      
      // Enter 键处理
      if (e.key === 'Enter' || e.keyCode === 13) {
        // 命令面板打开时：选择命令
        if (showCommandPalette.value) {
          e.preventDefault()
          const commands = filteredCommands.value
          if (commands.length > 0 && commands[selectedCommandIndex.value]) {
            executeCommand(commands[selectedCommandIndex.value])
          }
          return
        }
        
        // 命令面板关闭时：
        // Shift+Enter = 换行，Enter = 发送
        if (!e.shiftKey) {
          e.preventDefault()
          if (canSend.value) {
            sendMessage()
          }
        }
        // Shift+Enter 允许默认行为（换行）
        return
      }
      
      // 以下仅在命令面板打开时生效
      if (!showCommandPalette.value) return
      
      const commands = filteredCommands.value
      if (commands.length === 0) return
      
      // 上箭头
      if (e.key === 'ArrowUp' || e.keyCode === 38) {
        e.preventDefault()
        selectedCommandIndex.value = Math.max(0, selectedCommandIndex.value - 1)
      }
      // 下箭头
      else if (e.key === 'ArrowDown' || e.keyCode === 40) {
        e.preventDefault()
        selectedCommandIndex.value = Math.min(commands.length - 1, selectedCommandIndex.value + 1)
      }
    }
    
    // 执行命令
    const executeCommand = (cmd) => {
      console.log('执行命令:', cmd)
      
      // 添加用户消息（显示执行的命令）
      messages.value.push({
        role: 'user',
        content: `/${cmd.label}`,
        timestamp: new Date().toISOString()
      })
      
      // 清空输入框并关闭命令面板
      inputText.value = ''
      showCommandPalette.value = false
      selectedCommandIndex.value = 0
      
      // 特殊处理：切换方案命令（本地处理，不需要emit）
      if (cmd.command === 'switch_scheme') {
        setTimeout(() => {
          addAIMessage('正在加载该测站可用的预报方案...')
        }, 300)
        
        setTimeout(() => {
          showSchemeSelector()
        }, 500)
        
        scrollToBottom()
        return
      }
      
      // 特殊处理：天气预报命令（显示模态框）
      if (cmd.command === 'weather_forecast') {
        setTimeout(() => {
          openPageModal(
            `${window.location.origin}/#/pages/weather/forecast?stcd=${props.stcd}`,
            '东三省天气预报'
          )
          addAIMessage('✅ 已打开东三省天气预报系统')
        }, 300)
        
        scrollToBottom()
        return
      }
      
      // 特殊处理：水库雨情命令
      if (cmd.command === 'rainfall_detail') {
        setTimeout(() => {
          openPageModal(
            `${window.location.origin}/#/pages/rainfall/measured?basinCode=${props.stcd}`,
            `水库雨情 (${props.stcd})`
          )
          addAIMessage(`✅ 已打开测站 ${props.stcd} 的雨情详情`)
        }, 300)
        
        scrollToBottom()
        return
      }
      
      // 特殊处理：水库水情命令
      if (cmd.command === 'water_detail') {
        setTimeout(() => {
          openPageModal(
            `${window.location.origin}/#/pages/water/detail?stationCode=${props.stcd}`,
            `水库水情 (${props.stcd})`
          )
          addAIMessage(`✅ 已打开测站 ${props.stcd} 的水情详情`)
        }, 300)
        
        scrollToBottom()
        return
      }
      
      // 特殊处理：预报历史记录命令
      if (cmd.command === 'forecast_history') {
        // 使用预报配置的起始时间，格式化为标准格式
        let startTimeStr = props.forecastStartTime || new Date().toISOString().slice(0, 19).replace('T', ' ')
        
        // 如果格式是 "2025/05/19, 00:00"，转换为 "2025-05-19 00:00:00"
        if (startTimeStr.includes('/')) {
          startTimeStr = startTimeStr.replace(/\//g, '-').replace(', ', ' ')
          if (!startTimeStr.includes(':')) {
            startTimeStr += ':00'
          }
          if (startTimeStr.split(':').length === 2) {
            startTimeStr += ':00'
          }
        }
        
        addSystemMessage(
          `📚 **预报历史查询**\n\n正在查询测站 **${props.stcd}** 从 **${startTimeStr}** 起的历史预报记录...`,
          []
        )
        
        setTimeout(() => {
          // 使用组件方式打开（而非URL）
          showForecastHistory(startTimeStr)
        }, 300)
        
        scrollToBottom()
        return
      }
      
      // 特殊处理：假拟降雨场景命令
      if (cmd.command === 'hypothetical_rainfall') {
        console.log('🌦️ 假拟降雨场景检查:', {
          sessionId: props.sessionId,
          lastSessionId: props.lastSessionId,
          hasLastSessionId: !!props.lastSessionId
        })
        
        if (!props.lastSessionId) {
          addAIMessage('❌ 请先执行一次预报完成后才能创建假拟场景\n\n假拟降雨需要基于已完成的预报结果来生成不同降雨量的对比场景。')
          scrollToBottom()
          return
        }
        
        addSystemMessage(
          `🌦️ **假拟降雨场景生成**\n\n基于已完成的预报会话（Session: ${props.lastSessionId.slice(0, 8)}...）生成不同总降雨量的预报对比场景`,
          []
        )
        
        setTimeout(() => {
          showHypotheticalRainfall()
        }, 300)
        
        scrollToBottom()
        return
      }
      
      // 其他命令：触发到父组件
      emit('command', { type: cmd.command })
      
      // 显示AI反馈
      const feedbackMap = {
        'view_params': '正在跳转至模型参数配置区域...',
        'config_time': '正在跳转至预报时段配置区域...',
        'edit_rainfall': '正在跳转至降雨数据编辑区域...',
        'view_result': '正在跳转至预报结果查看区域...'
      }
      
      if (feedbackMap[cmd.command]) {
        setTimeout(() => {
          addAIMessage(feedbackMap[cmd.command])
        }, 300)
      }
      
      scrollToBottom()
    }
    
    // 处理焦点
    const handleFocus = () => {
      inputFocused.value = true
      console.log('输入框获得焦点')
      // 如果输入框有"/"，重新显示命令面板
      if (inputText.value.startsWith('/')) {
        showCommandPalette.value = true
      }
    }
    
    // 处理输入框失焦
    const handleInputBlur = () => {
      console.log('输入框失焦')
      // 延迟关闭，以便点击命令项能正确触发
      setTimeout(() => {
        inputFocused.value = false
        // 只有当输入框为空或不是"/"开头时才关闭命令面板
        if (!inputText.value.startsWith('/')) {
          showCommandPalette.value = false
          console.log('失焦后关闭命令面板')
        }
      }, 300)
    }
    
    // 发送消息
    const sendMessage = () => {
      // 如果命令面板打开且有选中项，执行命令
      if (showCommandPalette.value && filteredCommands.value.length > 0) {
        executeCommand(filteredCommands.value[selectedCommandIndex.value])
        return
      }
      
      if (!canSend.value) return

      const text = inputText.value.trim()
      
      // 添加用户消息
      messages.value.push({
        role: 'user',
        content: text,
        timestamp: new Date().toISOString()
      })

      inputText.value = ''
      showCommandPalette.value = false
      scrollToBottom()

      // 发送到WebSocket
      /*
      if (ws.value && ws.value.readyState === WebSocket.OPEN) {
        ws.value.send(JSON.stringify({
          stcd: props.stcd,
          message: text
        }))
      }
      */

      // Mock AI响应
      handleUserMessage(text)
    }

    // 快捷指令
    const sendQuickCommand = (command) => {
      inputText.value = command
      sendMessage()
    }

    // 显示方案选择器
    const showSchemeSelector = () => {
      if (availableSchemes.value.length > 0) {
        addAIMessage(
          '请选择一个预报方案：',
          availableSchemes.value.map(scheme => ({
            label: `${scheme.icon || '📊'} ${scheme.label}`,
            command: 'select_scheme',
            params: { scheme: scheme }
          }))
        )
      } else {
        addAIMessage('正在加载该测站可用的预报方案...')
        loadSchemes().then(() => {
          if (availableSchemes.value.length > 0) {
            showSchemeSelector()
          } else {
            addAIMessage('❌ 该测站暂无可用的预报方案配置')
          }
        })
      }
    }

    // 检测是否是参数调整请求
    const isParamAdjustmentRequest = (text) => {
      const keywords = ['改为', '设置', '调整', '增加', '减少', '修改', 'SA0', 'A参数', 'B参数', 
                       'C参数', 'IM参数', 'initial_state', 'parameters']
      return keywords.some(kw => text.includes(kw))
    }
    
    // 调用LLM API
    const callLLMAPI = async (message) => {
      const startTime = Date.now()
      try {
        // 优先使用 sessionId，如果为空则使用 lastSessionId
        // 这样可以在预报执行后继续对话（sessionId 被清空，但 lastSessionId 保留）
        const effectiveSessionId = props.sessionId || props.lastSessionId
        
        console.log('🔍 [LLM] 调用参数:', {
          conversationId: conversationId.value,
          message,
          sessionId: props.sessionId,
          lastSessionId: props.lastSessionId,
          effectiveSessionId: effectiveSessionId
        })
        
        const response = await llmApi.chat(conversationId.value, message, effectiveSessionId)
        const duration = ((Date.now() - startTime) / 1000).toFixed(2)
        console.log(`⏱️ LLM接口执行时间: ${duration}秒`)
        return response
      } catch (error) {
        const duration = ((Date.now() - startTime) / 1000).toFixed(2)
        console.error(`❌ LLM API调用失败 (耗时${duration}秒):`, error)
        throw error
      }
    }
    
    // 应用参数变化（LLM API已经在后端更新了参数，这里只需要更新前端）
    const applyParameterChanges = async (llmResponse) => {
      try {
        // LLM API返回的update_success表示后端是否成功更新
        if (llmResponse.update_success) {
          console.log('🔄 LLM更新成功，使用返回的参数...')
          
          // LLM API已经返回了更新后的完整参数，直接使用
          const currentParams = llmResponse.current_parameters
          
          if (!currentParams) {
            console.error('❌ LLM响应中没有 current_parameters')
            throw new Error('LLM响应数据不完整')
          }
          
          console.log('📦 LLM返回的参数:', currentParams)
          console.log('📦 initial_state:', currentParams.initial_state)
          console.log('📦 parameters:', currentParams.parameters)
          
          // 构建完整的参数对象（与 getModelParams 格式一致）
          const updatedParams = {
            id: props.currentParams?.id || null,
            modelType: props.currentParams?.modelType || null,
            plcd: props.currentParams?.plcd || null,
            initialState: currentParams.initial_state,
            parameters: currentParams.parameters,
            _meta: props.currentParams?._meta || null
          }
          
          console.log('📤 发送给父组件的参数:', updatedParams)
          
          // 通知父组件参数已更新
          emit('params-updated', updatedParams)
          
          // 计算变化的参数数量
          const changeCount = Object.keys(llmResponse.parameter_changes || {}).length
          
          return {
            success: true,
            message: llmResponse.update_message || `成功更新 ${changeCount} 个参数`
          }
        } else {
          // 参数验证失败或其他原因导致更新失败
          return {
            success: false,
            message: llmResponse.update_message || '参数更新失败',
            validationErrors: llmResponse.validation_errors
          }
        }
      } catch (error) {
        console.error('应用参数变化失败:', error)
        return {
          success: false,
          message: error.message || '参数更新失败'
        }
      }
    }
    
    // 处理用户消息
    const handleUserMessage = async (text) => {
      // 检查是否有有效的 sessionId 或 lastSessionId
      if (!props.sessionId && !props.lastSessionId) {
        addAIMessage(
          '⚠️ **预报会话未开始**\n\n请先选择预报方案并加载参数后，才能使用知汛助手。\n\n💡 **操作步骤：**\n1. 点击"切换方案"选择预报方案\n2. 配置模型参数和降雨数据\n3. 即可使用知汛助手进行参数调整或创建假拟降雨场景',
          [
            { label: '🔄 切换方案', command: 'switch_scheme' }
          ]
        )
        return
      }
      
      // 调用LLM API（让 LLM 来判断用户意图）
      isTyping.value = true
      isLLMThinking.value = true
        
        try {
          const llmResponse = await callLLMAPI(text)
          
          isTyping.value = false
          isLLMThinking.value = false
          
          console.log('🤖 [LLM] 响应数据:', llmResponse)
          console.log('🤖 [LLM] intent_type:', llmResponse.intent_type)
          
          // 根据 intent_type 分别处理
          if (llmResponse.intent_type === 'rainfall_scenario') {
            // 假拟降雨场景
            console.log('🌧️ [LLM] 识别为假拟降雨场景')
            console.log('🌧️ [LLM] rainfall_simulation:', llmResponse.rainfall_simulation)
            
            const content = llmResponse.message || '正在为您准备假拟降雨场景...'
            addSystemMessage(content, [], true)
            
            // 检查是否有 rainfall_simulation 数据
            if (llmResponse.rainfall_simulation && 
                llmResponse.rainfall_simulation.method && 
                llmResponse.rainfall_simulation.values) {
              
              const { method, values } = llmResponse.rainfall_simulation
              
              console.log('🌧️ [LLM] 提取配置:')
              console.log('   method:', method)
              console.log('   values:', values)
              console.log('   values类型:', typeof values, Array.isArray(values))
              console.log('   values内容:', JSON.stringify(values))
              
              // 先保存 LLM 配置
              llmHypotheticalConfig.value = { 
                method: method, 
                values: Array.isArray(values) ? values : []
              }
              
              console.log('🌧️ [LLM] 保存配置到 llmHypotheticalConfig:')
              console.log('   完整对象:', JSON.stringify(llmHypotheticalConfig.value))
              console.log('   method:', llmHypotheticalConfig.value.method)
              console.log('   values:', llmHypotheticalConfig.value.values)
              console.log('   lastSessionId:', props.lastSessionId)
              
              addSystemMessage(
                '✅ **假拟降雨配置已准备**\n\n正在打开假拟降雨页面...',
                [
                  { label: '🌧️ 打开假拟降雨', command: 'hypothetical_rainfall' }
                ]
              )
              
              // 使用 nextTick 确保响应式数据更新后再打开弹窗
              nextTick(() => {
                console.log('🌧️ [LLM] nextTick 后打开弹窗')
                console.log('🌧️ [LLM] 此时 llmHypotheticalConfig.value:', llmHypotheticalConfig.value)
                showHypotheticalRainfall()
              })
              
            } else {
              addSystemMessage(
                '⚠️ **数据不完整**\n\n无法解析假拟降雨配置，请提供更详细的描述。',
                []
              )
            }
            
          } else if (llmResponse.intent_type === 'parameter_modification') {
            // 参数修改（保持原有逻辑）
            console.log('⚙️ [LLM] 识别为参数修改')
            
            // 检查会话是否有效
            if (!props.sessionId || props.sessionId === 'null') {
              addAIMessage(
                '⚠️ **预报会话未开始**\n\n无法使用AI助手调整参数。请先选择预报方案并加载参数。',
                [
                  { label: '🔄 切换方案', command: 'switch_scheme' }
                ]
              )
              return
            }
            
            // 构建AI回复消息
            let content = llmResponse.message || '已处理您的请求。'
            
            // 添加参数变化说明
            if (llmResponse.parameter_changes && Object.keys(llmResponse.parameter_changes).length > 0) {
              content += '\n\n**📝 参数变化：**\n'
              for (const [key, value] of Object.entries(llmResponse.parameter_changes)) {
                content += `• ${key} → ${value}\n`
              }
            }
            
            // 添加说明
            if (llmResponse.explanation) {
              content += `\n**💡 说明：**\n${llmResponse.explanation}`
            }
            
            // 显示AI回复（使用markdown）
            addSystemMessage(content, [], true)
            
            // 应用参数变化
            if (llmResponse.parameter_changes && 
                Object.keys(llmResponse.parameter_changes).length > 0) {
              
              const applyResult = await applyParameterChanges(llmResponse)
              
              if (applyResult.success) {
                addSystemMessage(
                  `✅ **${applyResult.message}**\n\n参数已成功应用到水文模型。`,
                  [
                    { label: '📝 查看参数', command: 'view_params' },
                    { label: '🚀 执行预报', command: 'execute_forecast' }
                  ]
                )
              } else {
                // 显示错误和验证错误
                let errorMsg = `❌ **参数应用失败**\n\n${applyResult.message}`
                
                if (applyResult.validationErrors && applyResult.validationErrors.length > 0) {
                  errorMsg += '\n\n**验证错误：**\n'
                  applyResult.validationErrors.forEach(err => {
                    errorMsg += `• ${err}\n`
                  })
                }
                
                addSystemMessage(errorMsg, [
                  { label: '💡 查看说明', command: 'view_params' }
                ])
              }
            }
            
          } else {
            // unknown 或其他类型
            console.log('❓ [LLM] 未识别的意图类型:', llmResponse.intent_type)
            
            const content = llmResponse.message || '抱歉，我无法理解您的请求。'
            addSystemMessage(content, [], true)
          }
          
        } catch (error) {
          isTyping.value = false
          isLLMThinking.value = false
          
          let errorMessage = '⚠️ **处理请求时出现错误**\n\n'
          
          if (error.message && error.message.includes('会话不存在')) {
            errorMessage += '预报会话已失效或不存在。请尝试重新选择预报方案或修改参数以创建新的会话。'
          } else if (error.message && error.message.includes('Failed to fetch')) {
            errorMessage += '无法连接到AI服务器，请检查网络连接后重试。'
          } else {
            errorMessage += error.message || '未知错误'
          }
          
          addSystemMessage(errorMessage)
        }
    }

    // 执行操作
    const executeAction = (action) => {
      // 特殊处理方案选择
      if (action.command === 'select_scheme') {
        selectScheme(action.params.scheme)
      } else if (action.command === 'switch_scheme') {
        // 特殊处理切换方案（本地处理）
        showSchemeSelector()
      } else {
        // 发送其他命令到父组件
        emit('command', {
          type: action.command
        })
      }
    }
    
    // 打开页面模态框
    const openPageModal = (url, title) => {
      modalUrl.value = url
      modalTitle.value = title
      modalVisible.value = true
    }
    
    // 关闭页面模态框
    const closeModal = () => {
      modalVisible.value = false
      setTimeout(() => {
        modalUrl.value = ''
        modalTitle.value = ''
      }, 300)
    }
    
    // 打开预报历史查看器
    const showForecastHistory = (startTime) => {
      historyStartTime.value = startTime
      historyModalVisible.value = true
    }
    
    // 关闭预报历史查看器
    const closeForecastHistory = () => {
      historyModalVisible.value = false
    }

    // 打开假拟降雨界面
    const showHypotheticalRainfall = () => {
      console.log('🌦️ [ChatPanel] 打开假拟降雨界面')
      console.log('   lastSessionId:', props.lastSessionId)
      console.log('   llmHypotheticalConfig:', llmHypotheticalConfig.value)
      console.log('   llmHypotheticalConfig JSON:', JSON.stringify(llmHypotheticalConfig.value))
      
      // 检查 lastSessionId 是否有效
      if (!props.lastSessionId) {
        console.warn('⚠️ lastSessionId 为空，无法打开假拟降雨')
        addAIMessage(
          '❌ **无法打开假拟降雨**\n\n请先执行一次预报完成后才能创建假拟场景。\n\n假拟降雨需要基于已完成的预报结果来生成不同降雨量的对比场景。',
          [
            { label: '🔄 切换方案', command: 'switch_scheme' }
          ]
        )
        return
      }
      
      hypotheticalModalVisible.value = true
    }
    
    // 关闭假拟降雨界面
    const closeHypotheticalRainfall = () => {
      hypotheticalModalVisible.value = false
      // 清空 LLM 配置
      llmHypotheticalConfig.value = null
    }

    // 格式化时间
    const formatTime = (timestamp) => {
      const date = new Date(timestamp)
      return date.toLocaleTimeString('zh-CN', {
        hour: '2-digit',
        minute: '2-digit',
        second: '2-digit'
      })
    }

    // 滚动到底部
    const scrollToBottom = () => {
      nextTick(() => {
        const container = document.querySelector('.chat-messages')
        if (container) {
          container.scrollTop = container.scrollHeight
        }
      })
    }

    // 全局 ESC 键处理
    const handleGlobalKeyDown = (e) => {
      if (e.key === 'Escape' || e.keyCode === 27) {
        if (showCommandPalette.value) {
          e.preventDefault()
          showCommandPalette.value = false
          inputText.value = ''
        }
      }
    }

    onMounted(() => {
      loadSchemes()
      connectWebSocket()
      // 添加全局键盘监听
      window.addEventListener('keydown', handleGlobalKeyDown)
    })

    onUnmounted(() => {
      if (ws.value) {
        ws.value.close()
      }
      // 移除全局键盘监听
      window.removeEventListener('keydown', handleGlobalKeyDown)
    })

    watch(() => messages.value.length, () => {
      scrollToBottom()
    })

    // 获取方案描述
    const getSchemeDesc = (value) => {
      const descMap = {
        'DHF': '大伙房水文模型',
        'SMS3': '三水源新安江模型'
      }
      return descMap[value] || '洪水预报模型'
    }

    return {
      messages,
      inputText,
      inputFocused,
      isConnected,
      isTyping,
      messagesContainer,
      availableSchemes,
      quickCommands,
      hasMessages,
      canSend,
      showCommandPalette,
      selectedCommandIndex,
      filteredCommands,
      hasSearchText,
      commandGroups,
      modalVisible,
      modalUrl,
      modalTitle,
      historyModalVisible,
      historyStartTime,
      hypotheticalModalVisible,
      llmHypotheticalConfig,
      addSystemMessage,
      selectScheme,
      showSchemeSelector,
      sendMessage,
      sendQuickCommand,
      executeAction,
      executeCommand,
      handleInput,
      handleFocus,
      handleKeyDown,
      handleInputBlur,
      formatTime,
      openPageModal,
      closeModal,
      showForecastHistory,
      closeForecastHistory,
      showHypotheticalRainfall,
      closeHypotheticalRainfall,
      inputRef,
      getSchemeDesc
    }
  }
}
</script>

<style scoped>
.chat-panel {
  height: 100%;
  display: flex;
  flex-direction: column;
  background-color: #f5f7fa;
}

/* 头部 */
.chat-header {
  padding: 16px 20px;
  background-color: #fff;
  border-bottom: 1px solid #e4e7ed;
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex-shrink: 0;
}

.header-title {
  font-size: 16px;
  font-weight: 600;
  color: #303133;
}

.header-status {
  display: flex;
  align-items: center;
  gap: 6px;
}

.status-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background-color: #909399;
  transition: background-color 0.3s;
}

.status-dot.connected {
  background-color: #67c23a;
  animation: pulse 2s infinite;
}

@keyframes pulse {
  0%, 100% {
    opacity: 1;
  }
  50% {
    opacity: 0.5;
  }
}

.status-text {
  font-size: 12px;
  color: #909399;
}

/* 消息列表 */
.chat-messages {
  flex: 1;
  padding: 24px 20px;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 20px;
  background: linear-gradient(to bottom, #fafafa 0%, #ffffff 100%);
}

.message-item {
  display: flex;
  gap: 12px;
  animation: messageSlideIn 0.4s cubic-bezier(0.4, 0, 0.2, 1);
}

@keyframes messageSlideIn {
  from {
    opacity: 0;
    transform: translateY(16px) scale(0.95);
  }
  to {
    opacity: 1;
    transform: translateY(0) scale(1);
  }
}

.message-item.user {
  flex-direction: row-reverse;
}

.message-avatar {
  width: 32px;
  height: 32px;
  flex-shrink: 0;
  border-radius: 50%;
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 2px 6px rgba(102, 126, 234, 0.3);
}

.message-item.user .message-avatar {
  background: linear-gradient(135deg, #43a047 0%, #388e3c 100%);
  box-shadow: 0 2px 6px rgba(67, 160, 71, 0.3);
}

.avatar-icon {
  font-size: 18px;
}

.message-content {
  flex: 1;
  max-width: 80%;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.message-item.user .message-content {
  align-items: flex-end;
}

.message-header {
  display: flex;
  align-items: center;
  gap: 8px;
}

.message-item.user .message-header {
  flex-direction: row-reverse;
}

.message-sender {
  font-size: 13px;
  color: #5f6368;
  font-weight: 600;
  letter-spacing: 0.2px;
}

.message-time {
  font-size: 11px;
  color: #9aa0a6;
  font-weight: 400;
}

.message-text {
  padding: 14px 18px;
  background-color: #f8f9fa;
  border-radius: 12px;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
  font-size: 14px;
  color: #2c3e50;
  line-height: 1.7;
  white-space: pre-wrap;
  word-break: break-word;
  border: 1px solid #e8eaed;
  transition: all 0.2s ease;
  user-select: text;  /* 允许选择文字 */
  -webkit-user-select: text;  /* Safari */
  -moz-user-select: text;  /* Firefox */
  -ms-user-select: text;  /* IE/Edge */
  cursor: text;  /* 显示文本光标 */
}

.message-text:hover {
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
}

/* Markdown内容样式 */
.markdown-content {
  width: 100%;
  overflow-x: auto;
}

.markdown-content table {
  max-width: 100%;
  overflow-x: auto;
  display: block;
}

.message-item.user .message-text {
  background: linear-gradient(135deg, #1976d2 0%, #1565c0 100%);
  color: #fff;
  border: none;
  box-shadow: 0 2px 6px rgba(25, 118, 210, 0.25);
}

.message-item.user .message-text:hover {
  box-shadow: 0 3px 10px rgba(25, 118, 210, 0.35);
}

.message-actions {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
  margin-top: 4px;
}

.action-btn {
  padding: 8px 16px;
  background-color: #fff;
  border: 1.5px solid #e0e0e0;
  border-radius: 20px;
  color: #1976d2;
  font-size: 13px;
  font-weight: 500;
  cursor: pointer;
  transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.06);
}

.action-btn:hover {
  background: linear-gradient(135deg, #1976d2 0%, #1565c0 100%);
  color: #fff;
  border-color: #1976d2;
  transform: translateY(-1px);
  box-shadow: 0 3px 8px rgba(25, 118, 210, 0.25);
}

.action-btn:active {
  transform: translateY(0);
  box-shadow: 0 1px 3px rgba(25, 118, 210, 0.2);
}

/* 主要操作按钮（恢复session） */
.action-btn.primary {
  background: linear-gradient(135deg, #67c23a 0%, #5daf34 100%);
  color: #fff;
  border-color: #67c23a;
  box-shadow: 0 2px 6px rgba(103, 194, 58, 0.25);
}

.action-btn.primary:hover {
  background: linear-gradient(135deg, #85ce61 0%, #67c23a 100%);
  border-color: #85ce61;
  box-shadow: 0 3px 10px rgba(103, 194, 58, 0.35);
}

.action-btn.primary:active {
  box-shadow: 0 1px 3px rgba(103, 194, 58, 0.2);
}

/* 次要操作按钮（新建session） */
.action-btn.secondary {
  background-color: #fff;
  color: #909399;
  border-color: #dcdfe6;
}

.action-btn.secondary:hover {
  background: linear-gradient(135deg, #909399 0%, #787c82 100%);
  color: #fff;
  border-color: #909399;
  box-shadow: 0 3px 8px rgba(144, 147, 153, 0.25);
}

/* 输入中提示 */
.typing-indicator {
  padding: 12px 16px;
  background-color: #fff;
  border-radius: 8px;
  display: flex;
  gap: 4px;
}

.typing-indicator .dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background-color: #909399;
  animation: typing 1.4s infinite;
}

.typing-indicator .dot:nth-child(2) {
  animation-delay: 0.2s;
}

.typing-indicator .dot:nth-child(3) {
  animation-delay: 0.4s;
}

@keyframes typing {
  0%, 60%, 100% {
    transform: translateY(0);
  }
  30% {
    transform: translateY(-10px);
  }
}

/* 预报方案选择 */
.scheme-selection {
  position: relative;
  padding: 32px 24px;
  display: flex;
  flex-direction: column;
  gap: 28px;
  background: linear-gradient(135deg, #f8faff 0%, #f0f5ff 100%);
  overflow: hidden;
  animation: fadeIn 0.6s cubic-bezier(0.4, 0, 0.2, 1);
}

/* 背景装饰 */
.bg-decoration {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  z-index: 0;
}

.decoration-circle {
  position: absolute;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(64, 158, 255, 0.08) 0%, rgba(64, 158, 255, 0) 70%);
  animation: float 8s ease-in-out infinite;
}

.circle-1 {
  width: 300px;
  height: 300px;
  top: -100px;
  right: -50px;
  animation-delay: 0s;
}

.circle-2 {
  width: 200px;
  height: 200px;
  bottom: 100px;
  left: -50px;
  animation-delay: 2s;
}

.circle-3 {
  width: 150px;
  height: 150px;
  top: 50%;
  right: 10%;
  animation-delay: 4s;
}

@keyframes float {
  0%, 100% {
    transform: translateY(0) scale(1);
  }
  50% {
    transform: translateY(-20px) scale(1.05);
  }
}

/* 头部区域 */
.selection-header {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  text-align: center;
}

.header-icon-wrapper {
  width: 72px;
  height: 72px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  border-radius: 20px;
  box-shadow: 0 8px 24px rgba(102, 126, 234, 0.3);
  animation: iconPulse 2s ease-in-out infinite;
}

@keyframes iconPulse {
  0%, 100% {
    transform: scale(1);
    box-shadow: 0 8px 24px rgba(102, 126, 234, 0.3);
  }
  50% {
    transform: scale(1.05);
    box-shadow: 0 12px 32px rgba(102, 126, 234, 0.4);
  }
}

.header-icon {
  font-size: 36px;
  filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.1));
}

.selection-title {
  font-size: 24px;
  font-weight: 700;
  color: #1a1a1a;
  letter-spacing: 0.5px;
}

.selection-desc {
  font-size: 14px;
  color: #666;
  line-height: 1.6;
  display: flex;
  align-items: center;
  gap: 8px;
}

.station-badge {
  display: inline-block;
  padding: 4px 12px;
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  color: #fff;
  border-radius: 20px;
  font-size: 13px;
  font-weight: 600;
  box-shadow: 0 2px 8px rgba(102, 126, 234, 0.3);
}

/* 方案卡片容器 */
.scheme-cards {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  gap: 16px;
}

/* 方案卡片 */
.scheme-option-card {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 20px;
  background: #fff;
  border: 2px solid #e8ecf4;
  border-radius: 16px;
  cursor: pointer;
  transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
  overflow: hidden;
  animation: slideIn 0.5s ease-out backwards;
}

.card-delay-0 {
  animation-delay: 0.1s;
}

.card-delay-1 {
  animation-delay: 0.2s;
}

@keyframes slideIn {
  from {
    opacity: 0;
    transform: translateX(-30px);
  }
  to {
    opacity: 1;
    transform: translateX(0);
  }
}

.card-glow {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: linear-gradient(135deg, rgba(102, 126, 234, 0.1) 0%, rgba(118, 75, 162, 0.1) 100%);
  opacity: 0;
  transition: opacity 0.4s ease;
  pointer-events: none;
}

.scheme-option-card:hover {
  border-color: #667eea;
  transform: translateY(-4px);
  box-shadow: 0 12px 32px rgba(102, 126, 234, 0.2);
}

.scheme-option-card:hover .card-glow {
  opacity: 1;
}

.scheme-option-card:active {
  transform: translateY(-2px);
}

/* 卡片左侧内容 */
.scheme-card-left {
  display: flex;
  align-items: center;
  gap: 16px;
  flex: 1;
}

.scheme-icon-bg {
  position: relative;
  width: 64px;
  height: 64px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: linear-gradient(135deg, #f0f5ff 0%, #e6f0ff 100%);
  border-radius: 16px;
  flex-shrink: 0;
  transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
}

.scheme-option-card:hover .scheme-icon-bg {
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  transform: rotate(-5deg) scale(1.1);
  box-shadow: 0 8px 20px rgba(102, 126, 234, 0.3);
}

.scheme-card-icon {
  font-size: 32px;
  transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
}

.scheme-option-card:hover .scheme-card-icon {
  transform: scale(1.2);
  filter: drop-shadow(0 4px 8px rgba(0, 0, 0, 0.2));
}

.scheme-card-content {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.scheme-card-name {
  font-size: 18px;
  font-weight: 700;
  color: #1a1a1a;
  letter-spacing: 0.3px;
  transition: color 0.3s ease;
}

.scheme-option-card:hover .scheme-card-name {
  color: #667eea;
}

.scheme-card-desc {
  font-size: 13px;
  color: #888;
  line-height: 1.4;
}

/* 卡片右侧操作 */
.scheme-card-action {
  flex-shrink: 0;
}

.action-circle {
  width: 44px;
  height: 44px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  border-radius: 50%;
  color: #fff;
  transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
  box-shadow: 0 4px 12px rgba(102, 126, 234, 0.3);
}

.scheme-option-card:hover .action-circle {
  transform: translateX(6px) scale(1.1);
  box-shadow: 0 8px 20px rgba(102, 126, 234, 0.5);
}

.action-circle svg {
  transition: transform 0.3s ease;
}

.scheme-option-card:hover .action-circle svg {
  transform: translateX(2px);
}

/* 底部提示 */
.selection-note {
  position: relative;
  z-index: 1;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 16px 20px;
  background: rgba(255, 255, 255, 0.9);
  border: 1px solid #e8ecf4;
  border-left: 4px solid #667eea;
  border-radius: 12px;
  backdrop-filter: blur(10px);
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
}

.note-icon-wrapper {
  width: 32px;
  height: 32px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  border-radius: 50%;
  color: #fff;
  flex-shrink: 0;
}

.note-text {
  flex: 1;
  font-size: 13px;
  color: #666;
  line-height: 1.6;
}

/* 快捷指令 */
.quick-commands {
  padding: 20px;
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.commands-title {
  font-size: 13px;
  color: #909399;
  font-weight: 500;
}

.commands-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 10px;
}

.command-card {
  padding: 12px;
  background-color: #fff;
  border: 1px solid #e4e7ed;
  border-radius: 8px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  cursor: pointer;
  transition: all 0.3s;
}

.command-card:hover {
  border-color: #409eff;
  background-color: #ecf5ff;
  transform: translateY(-2px);
  box-shadow: 0 2px 8px rgba(64, 158, 255, 0.15);
}

.command-icon {
  font-size: 24px;
}

.command-label {
  font-size: 12px;
  color: #606266;
  text-align: center;
}

/* 输入框 */
.chat-input-container {
  position: relative;
  padding: 16px 20px;
  background-color: #fff;
  border-top: 1px solid #e4e7ed;
  flex-shrink: 0;
}

/* 命令面板 */
.command-palette {
  position: absolute;
  bottom: 100%;
  left: 20px;
  right: 20px;
  margin-bottom: 8px;
  background: #fff;
  border-radius: 8px;
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
  overflow: hidden;
  z-index: 1000;
  animation: slideUp 0.2s ease-out;
}

@keyframes slideUp {
  from {
    opacity: 0;
    transform: translateY(10px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

.command-palette-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 12px 16px;
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  color: #fff;
}

.palette-title {
  font-size: 14px;
  font-weight: 600;
}

.palette-hint {
  font-size: 11px;
  opacity: 0.9;
}

/* 搜索结果列表 */
.command-palette-list {
  max-height: 400px;
  overflow-y: auto;
  padding: 8px;
}

.palette-command-item {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 14px;
  cursor: pointer;
  transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
  border-radius: 8px;
  margin-bottom: 4px;
}

.palette-command-item:hover {
  background-color: #f5f7fa;
  transform: translateX(2px);
}

.palette-command-item.active {
  background: linear-gradient(90deg, #e8eaf6 0%, #f3e5f5 100%);
  box-shadow: 0 2px 8px rgba(102, 126, 234, 0.15);
}

.cmd-icon-wrapper {
  width: 36px;
  height: 36px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 8px;
  flex-shrink: 0;
  transition: transform 0.2s ease;
}

.palette-command-item:hover .cmd-icon-wrapper {
  transform: scale(1.1);
}

.palette-cmd-icon {
  font-size: 20px;
}

.cmd-content {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.palette-cmd-label {
  font-size: 14px;
  font-weight: 500;
  color: #303133;
  line-height: 1.3;
}

.palette-cmd-group {
  font-size: 11px;
  color: #909399;
  opacity: 0.8;
}

.palette-empty {
  padding: 60px 20px;
  text-align: center;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
}

.empty-icon {
  font-size: 48px;
  opacity: 0.3;
}

.empty-text {
  color: #909399;
  font-size: 14px;
}

/* 分组视图 */
.command-groups {
  max-height: 450px;
  overflow-y: auto;
  padding: 12px;
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 12px;
}

.command-group {
  background-color: #fafbfc;
  border-radius: 10px;
  overflow: hidden;
  border: 1px solid #e8eaed;
  transition: all 0.2s ease;
}

.command-group:hover {
  border-color: #d0d7de;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
}

.group-header {
  padding: 12px 14px;
  background: linear-gradient(135deg, rgba(255,255,255,0.9) 0%, rgba(255,255,255,0.6) 100%);
  border-bottom: 2px solid;
  display: flex;
  align-items: center;
  gap: 8px;
}

.group-icon {
  font-size: 18px;
}

.group-title {
  font-size: 13px;
  font-weight: 600;
  color: #24292f;
  letter-spacing: 0.3px;
}

.group-commands {
  padding: 6px;
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.group-command-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px;
  border-radius: 6px;
  cursor: pointer;
  transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
  background-color: #fff;
}

.group-command-item:hover {
  background: linear-gradient(135deg, #f6f8fa 0%, #fff 100%);
  transform: translateX(3px);
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.08);
}

.group-command-item .cmd-icon-wrapper {
  width: 32px;
  height: 32px;
  border-radius: 6px;
}

.cmd-icon {
  font-size: 16px;
}

.cmd-info {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}

.cmd-name {
  font-size: 13px;
  font-weight: 500;
  color: #24292f;
  line-height: 1.2;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.cmd-desc {
  font-size: 11px;
  color: #57606a;
  line-height: 1.3;
  opacity: 0.8;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.input-wrapper {
  display: flex;
  gap: 12px;
  align-items: flex-end;
}

.chat-input {
  flex: 1;
  min-height: 40px;
  max-height: 120px;
  padding: 10px 12px;
  border: 1px solid #dcdfe6;
  border-radius: 6px;
  font-size: 14px;
  color: #606266;
  resize: none;
  transition: all 0.3s;
}

.chat-input:focus {
  border-color: #409eff;
  outline: none;
  box-shadow: 0 0 0 2px rgba(64, 158, 255, 0.1);
}

.send-btn {
  width: 40px;
  height: 40px;
  padding: 0;
  border: none;
  border-radius: 50%;
  background: linear-gradient(135deg, #409eff 0%, #3a8ee6 100%);
  color: #fff;
  font-size: 20px;
  cursor: pointer;
  transition: all 0.3s;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}

.send-btn:hover:not([disabled]) {
  transform: scale(1.1);
  box-shadow: 0 4px 12px rgba(64, 158, 255, 0.3);
}

.send-btn[disabled] {
  background: #c0c4cc;
  cursor: not-allowed;
}

.send-icon {
  display: block;
  line-height: 1;
}

.input-hint {
  margin-top: 8px;
  font-size: 12px;
  color: #909399;
  animation: fadeIn 0.3s;
}

@keyframes fadeIn {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

/* 滚动条样式 */
.chat-messages::-webkit-scrollbar {
  width: 6px;
}

.chat-messages::-webkit-scrollbar-track {
  background: #f1f1f1;
}

.chat-messages::-webkit-scrollbar-thumb {
  background: #c1c1c1;
  border-radius: 3px;
}

.chat-messages::-webkit-scrollbar-thumb:hover {
  background: #a8a8a8;
}

/* 预报历史模态框样式 */
.history-modal-overlay {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(0, 0, 0, 0.75);
  backdrop-filter: blur(8px);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 9999;
  animation: fadeIn 0.3s ease;
}

.history-modal-content {
  width: 90%;
  height: 90%;
  max-width: 1600px;
  background: linear-gradient(135deg, #0f0c29 0%, #302b63 50%, #24243e 100%);
  border-radius: 24px;
  box-shadow: 0 25px 100px rgba(0, 0, 0, 0.5);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  animation: slideUp 0.4s ease;
}

.history-modal-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 24px 32px;
  background: rgba(255, 255, 255, 0.05);
  border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}

.history-modal-title {
  color: white;
  font-size: 20px;
  font-weight: 700;
  letter-spacing: 0.5px;
}

.history-modal-close {
  width: 36px;
  height: 36px;
  border: none;
  background: rgba(255, 255, 255, 0.1);
  color: white;
  font-size: 20px;
  border-radius: 50%;
  cursor: pointer;
  transition: all 0.3s ease;
  display: flex;
  align-items: center;
  justify-content: center;
}

.history-modal-close:hover {
  background: rgba(255, 255, 255, 0.2);
  transform: rotate(90deg);
}

.history-modal-body {
  flex: 1;
  overflow: hidden;
}

@keyframes fadeIn {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

@keyframes slideUp {
  from {
    transform: translateY(50px);
    opacity: 0;
  }
  to {
    transform: translateY(0);
    opacity: 1;
  }
}
</style>

